#!/usr/bin/env python3
"""
事件属性引用修复脚本
修复事件定义中props引用的属性不在attributes中定义的问题
"""

import os
import re
import yaml
import shutil
from pathlib import Path
from typing import Dict, List, Set, Any

def load_yaml_file(file_path: str) -> Dict[str, Any]:
    """加载YAML文件"""
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            return yaml.safe_load(f) or {}
    except Exception as e:
        print(f"错误: 无法加载文件 {file_path}: {e}")
        return {}

def save_yaml_file(file_path: str, data: Dict[str, Any]) -> bool:
    """保存YAML文件"""
    try:
        with open(file_path, 'w', encoding='utf-8') as f:
            yaml.dump(data, f, default_flow_style=False, allow_unicode=True, indent=2)
        return True
    except Exception as e:
        print(f"错误: 无法保存文件 {file_path}: {e}")
        return False

def get_entity_attributes(entity_data: Dict[str, Any]) -> Set[str]:
    """获取实体的所有属性名称"""
    attributes = set()
    if 'attributes' in entity_data:
        attributes.update(entity_data['attributes'].keys())
    return attributes

def get_missing_event_props(entity_data: Dict[str, Any]) -> Dict[str, List[str]]:
    """获取事件中缺失的属性"""
    attributes = get_entity_attributes(entity_data)
    missing_props = {}
    
    if 'events' in entity_data:
        for event_name, event_data in entity_data['events'].items():
            if 'props' in event_data:
                missing = []
                for prop in event_data['props']:
                    if prop not in attributes:
                        missing.append(prop)
                if missing:
                    missing_props[event_name] = missing
    
    return missing_props

def add_missing_attributes(entity_data: Dict[str, Any], missing_props: Dict[str, List[str]]) -> Dict[str, Any]:
    """添加缺失的属性定义"""
    if not missing_props:
        return entity_data
    
    # 确保attributes存在
    if 'attributes' not in entity_data:
        entity_data['attributes'] = {}
    
    # 收集所有缺失的属性
    all_missing = set()
    for props in missing_props.values():
        all_missing.update(props)
    
    # 为缺失的属性添加合理的定义
    attribute_definitions = {
        'updatedFields': {
            'type': 'json',
            'description': '更新的字段信息'
        },
        'deactivatedAt': {
            'type': 'datetime',
            'description': '停用时间'
        },
        'oldStatus': {
            'type': 'string',
            'description': '旧状态'
        },
        'newStatus': {
            'type': 'string',
            'description': '新状态'
        },
        'oldProgress': {
            'type': 'integer',
            'description': '旧进度'
        },
        'newProgress': {
            'type': 'integer',
            'description': '新进度'
        },
        'assignedAt': {
            'type': 'datetime',
            'description': '分配时间'
        },
        'role': {
            'type': 'string',
            'description': '角色'
        },
        'addedAt': {
            'type': 'datetime',
            'description': '添加时间'
        },
        'removedAt': {
            'type': 'datetime',
            'description': '移除时间'
        },
        'completedAt': {
            'type': 'datetime',
            'description': '完成时间'
        },
        'submittedAt': {
            'type': 'datetime',
            'description': '提交时间'
        },
        'approvedBy': {
            'type': 'uuid',
            'description': '审批人ID'
        },
        'approvedAt': {
            'type': 'datetime',
            'description': '审批时间'
        },
        'effectiveDate': {
            'type': 'date',
            'description': '生效日期'
        },
        'activatedAt': {
            'type': 'datetime',
            'description': '激活时间'
        },
        'reason': {
            'type': 'string',
            'description': '原因'
        },
        'terminatedAt': {
            'type': 'datetime',
            'description': '终止时间'
        },
        'confirmedAt': {
            'type': 'datetime',
            'description': '确认时间'
        },
        'trackingNumber': {
            'type': 'string',
            'description': '跟踪号'
        },
        'shippedAt': {
            'type': 'datetime',
            'description': '发货时间'
        },
        'deliveredAt': {
            'type': 'datetime',
            'description': '交付时间'
        },
        'cancelledAt': {
            'type': 'datetime',
            'description': '取消时间'
        }
    }
    
    # 添加缺失的属性
    for prop in all_missing:
        if prop in attribute_definitions:
            entity_data['attributes'][prop] = attribute_definitions[prop]
            print(f"  添加属性: {prop}")
        else:
            # 为未知属性添加通用定义
            entity_data['attributes'][prop] = {
                'type': 'string',
                'description': f'{prop}属性'
            }
            print(f"  添加通用属性: {prop}")
    
    return entity_data

def process_yaml_file(file_path: str) -> bool:
    """处理单个YAML文件"""
    print(f"处理文件: {file_path}")
    
    # 创建备份
    backup_path = f"{file_path}.backup"
    if not os.path.exists(backup_path):
        shutil.copy2(file_path, backup_path)
        print(f"  创建备份: {backup_path}")
    
    # 加载文件
    data = load_yaml_file(file_path)
    if not data:
        return False
    
    modified = False
    
    # 处理每个实体
    if 'entities' in data:
        for entity_name, entity_data in data['entities'].items():
            print(f"  检查实体: {entity_name}")
            
            # 获取缺失的事件属性
            missing_props = get_missing_event_props(entity_data)
            
            if missing_props:
                print(f"    发现缺失属性: {missing_props}")
                # 添加缺失的属性
                data['entities'][entity_name] = add_missing_attributes(entity_data, missing_props)
                modified = True
            else:
                print(f"    无缺失属性")
    
    # 保存修改后的文件
    if modified:
        if save_yaml_file(file_path, data):
            print(f"  ✓ 文件已更新")
            return True
        else:
            print(f"  ✗ 文件更新失败")
            return False
    else:
        print(f"  - 无需更新")
        return True

def process_directory(directory: str) -> None:
    """处理目录下的所有YAML文件"""
    directory_path = Path(directory)
    
    if not directory_path.exists():
        print(f"错误: 目录不存在 {directory}")
        return
    
    yaml_files = list(directory_path.glob("*.yml")) + list(directory_path.glob("*.yaml"))
    
    if not yaml_files:
        print(f"在目录 {directory} 中未找到YAML文件")
        return
    
    print(f"在目录 {directory} 中找到 {len(yaml_files)} 个YAML文件")
    
    success_count = 0
    fail_count = 0
    
    for file_path in yaml_files:
        # 跳过备份文件
        if file_path.name.endswith('.backup'):
            continue
            
        try:
            if process_yaml_file(str(file_path)):
                success_count += 1
            else:
                fail_count += 1
        except Exception as e:
            print(f"处理文件 {file_path} 时出错: {e}")
            fail_count += 1
    
    print(f"\n处理完成:")
    print(f"  成功: {success_count} 个文件")
    print(f"  失败: {fail_count} 个文件")
    
    if fail_count == 0:
        print("✓ 所有文件处理成功!")
    
    print(f"\n提示:")
    print(f"  - 运行语法检查: npx tsx src/cli/syntax-check.ts models")
    print(f"  - 恢复备份: cd {directory} && for file in *.backup; do mv \"$file\" \"${{file%.backup}}\"; done")

if __name__ == "__main__":
    import sys
    
    if len(sys.argv) != 2:
        print("用法: python3 fix-event-props.py <目录路径>")
        print("示例: python3 fix-event-props.py models/")
        sys.exit(1)
    
    directory = sys.argv[1]
    process_directory(directory)